#ifndef PROCTHREAD_H
#define PROCTHREAD_H

#include <QThread>
#include <QColor>
#include <QPixmap>
#include <QPainter>
#include <QDebug>

#include <src\projectHeaders.h>


#define SLEEP_TIME 120

//生成随机数据线程
class SpawnDataThread : public QThread {
Q_OBJECT
public:
    explicit SpawnDataThread(QObject *parent = nullptr);

    /**
     * 信号槽 接收迷宫大小数据
     * @param n 行数
     * @param m 列数
     */
    void receiveSize(int n, int m, bool isEdge);

protected:
    /**
     * 线程执行体
     */
    void run() override;

private:
    int m_n = 9; // 行数
    int m_m = 9; // 列数

    bool m_isEdge;

signals:

    /**
     * 信号槽 发送数据是否生成成功数据
     * @param isSpawnDataSuccessful 是否成功
     */
    void sendSuccessful(bool isSpawnDataSuccessful);

};

//算法执行体线程父类
class ProcThread : public QThread {
Q_OBJECT
public:
    explicit ProcThread(QObject *parent = nullptr);

    void receiveSize(int squareSize, int interval);

protected:
    /**
     * 线程执行体
     */
    void run() override;

    int m_n = 9; // 行数
    int m_m = 9; // 列数

    PII m_start; // 起点
    PII m_end; // 终点

    vector<vector<int>> m_mp;        // 迷宫的样子  mp[i][j]==0 不可通行   mp[i][j]==1可以通行
    map<pair<PII, PII >, int> m_edge; // 点与点之间的权值  edge[{x1,y1},{x2,y2}]点(x1,y1)到(x2,y2)之间的距离
    int m_dx[4] = {0, 1, 0, -1};
    int m_dy[4] = {1, 0, -1, 0}; // 方向分量

    static pair<PII, PII > ptp(int x1, int y1, int x2, int y2) {
        return make_pair(make_pair(x1, y1), make_pair(x2, y2));
    }

    int m_squareSize;

    int m_interval; // 图形化每个格子的间隙

    int sleepTimes = 0; //动画效果sleep次数

private:
    /**
     * 图形化迷宫初始布局
     */
    void SpawnLayout();

    /**
     * 读入迷宫数据
     */
    void InputData();

signals:

    /**
     * 信号槽 绘制尝试寻找路径途中走到的点位
     * @param type 以行号0还是坐标1去绘制
     * @param x 行号/x坐标
     * @param y 列号/y坐标
     * @param color 绘制颜色
     */
    void drawProc(int type, int x, int y, const QColor &color);

    void sendSpentTime(long long time);
};

//AStar算法执行体线程
class AStarProcThread : public ProcThread {
Q_OBJECT
public:
    explicit AStarProcThread(QObject *parent = nullptr);

protected:
    void run() override;

private:
    int AS_ans; //  A*的答案

signals:
};

//Dijkstra算法执行体线程
class DijkstraProcThread : public ProcThread {
Q_OBJECT
public:
    explicit DijkstraProcThread(QObject *parent = nullptr);

protected:
    void run() override;

private:
    int djstr_ans;                  // 迪杰斯特拉的答案

signals:
};

//Bfs算法执行体线程
class BfsProcThread : public ProcThread {
Q_OBJECT
public:
    explicit BfsProcThread(QObject *parent = nullptr);

protected:
    void run() override;

signals:
};

//Dfs算法执行体线程
class DfsProcThread : public ProcThread {
Q_OBJECT
public:
    explicit DfsProcThread(QObject *parent = nullptr);

protected:
    void run() override;

private:
    map<PII, bool> m_faw_tmp;
    vector<vector<PII>> m_way; // 存放所有路径，m_way[i]存储所有的路径，m_way[i][j]表示第i个路径的第j步走到的点的坐标{x,y};
    // 存储路径时，先开一个vector<PII> tmp暂时存放当前路径，再把当前路径push_back到way中
    int find_ans = 0;

    void dfs(PII &now, vector<PII > res) {

//        qDebug() << "("<<now.first<< "," <<now.second << ") ";
        emit drawProc(0, now.first, now.second, Qt::blue);
        QThread::msleep(SLEEP_TIME);
        ++sleepTimes;

        res.push_back(now);
        if (find_ans == 1)
            return;
        if (now == m_end) {
            m_way.push_back(res);
            find_ans = 1;
//            qDebug() << "==========";
//            qDebug() << "("<<now.first<< "," <<now.second << ") ";
//            qDebug() << "==========";
            return;
        }
        for (int i = 0; i < 4; i++) {
            PII next;
            next.first = now.first + m_dx[i], next.second = now.second + m_dy[i];
            if (0 <= next.first && next.first < m_n && 0 <= next.second && next.second < m_m)
                if (m_mp[next.first][next.second] == 1)
                    if (!m_faw_tmp[next]) {
                        m_faw_tmp[next] = true;
                        dfs(next, res);
                        //   m_faw_tmp[next] = false;
                        if (find_ans == 1)
                            return;
                    }
        }

    };

signals:
};

#endif // PROCTHREAD_H
